home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
User's Choice Windows CD
/
User's Choice Windows CD (CMS Software)(1993).iso
/
utility2
/
uwserver.zip
/
UWSERVER.TAR
/
lib
/
uw_options.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-01-25
|
7KB
|
259 lines
/*
* uw library - uw_options
*
* Copyright 1986 by John D. Bruner. All rights reserved. Permission to
* copy this program is given provided that the copy is not sold and that
* this copyright notice is included.
*/
#include <sys/types.h>
#include <sys/file.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <strings.h>
#include <signal.h>
#include <errno.h>
#include "uwlib.h"
#ifndef FD_SET
#define FD_SET(n,p) ((p)->fds_bits[0] |= (1 << (n)))
#define FD_CLR(n,p) ((p)->fds_bits[0] &= ~(1 << (n)))
#define FD_ISSET(n,p) ((p)->fds_bits[0] & (1 << (n)))
#define FD_ZERO(p) ((p)->fds_bits[0] = 0)
#define FD_SETSIZE (NBBY*sizeof(long))
#endif
#ifndef sigmask
#define sigmask(m) (1 << ((m)-1))
#endif
#ifndef htons
/* These should have been defined in <netinet/in.h>, but weren't (in 4.2BSD) */
extern unsigned short htons(), ntohs();
extern unsigned long htonl(), ntohl();
#endif
static UWIN *fdmap;
static int (*oldsigio)();
static struct fd_set fdmask;
static int nfds;
extern char *malloc();
uw_optinit(fd, uwin)
int fd;
UWIN uwin;
{
register int i, flags;
static int first = 1;
extern uw_optinput();
/*
* The first time through, allocate the file descriptor map and
* bitmask, and cause SIGIO traps to be handled by uw_optinput.
*/
if (first) {
first = 0;
nfds = getdtablesize();
fdmap = (UWIN *)malloc((unsigned)(sizeof(UWIN)*nfds));
if (fdmap != (UWIN *)0)
for (i = 0; i < nfds; i++)
fdmap[i] = (UWIN)0;
oldsigio = signal(SIGIO, uw_optinput);
FD_ZERO(&fdmask);
}
/*
* Add the new control fd to the map and mask. Set the owner
* to this process
*/
if (fd >= 0 && fd < nfds && uwin != (UWIN)0 && fdmap != (UWIN *)0) {
fdmap[fd] = uwin;
FD_SET(fd, &fdmask);
#ifdef SETOWN_BUG
(void)fcntl(fd, F_SETOWN, -getpid());
#else
(void)fcntl(fd, F_SETOWN, getpid());
#endif
if ((flags = fcntl(fd, F_GETFL, 0)) >= 0)
(void)fcntl(fd, F_SETFL, flags|FASYNC|FNDELAY);
uwin->uwi_ipclen = 0;
}
}
uw_optdone(fd)
{
register int flags;
/*
* Turn off asynchronous I/O notification and remove the
* map and mask information for "fd". We do not close the
* file descriptor, however -- the caller is expected to
* take care of that.
*/
if (fd >= 0 && fd < nfds && fdmap != (UWIN *)0) {
if ((flags = fcntl(fd, F_GETFL, 0)) >= 0)
(void)fcntl(fd, F_SETFL, flags&~FASYNC);
else
(void)fcntl(fd, F_SETFL, 0);
(void)fcntl(fd, F_SETFL, 0);
fdmap[fd] = (UWIN)0;
FD_CLR(fd, &fdmask);
}
}
static
uw_optinput(sig, code, scp)
int sig, code;
struct sigcontext *scp;
{
register int k, n, fd;
register UWIN uwin;
register struct uwoption *uwop;
register union uwoptval *uwov;
uwopt_t optnum;
uwoptcmd_t optcmd;
uwfnptr_t userfn;
int oldmask;
struct timeval timeo;
struct fd_set ready;
extern int errno;
/*
* This routine is called when input is waiting on a control
* file descriptor.
*/
oldmask = sigblock(sigmask(SIGALRM));
do {
ready = fdmask;
timeo.tv_sec = 0;
timeo.tv_usec = 0;
n = select(nfds, &ready, (struct fd_set *)0,
(struct fd_set *)0, &timeo);
if (n < 0 && errno == EBADF) {
/*
* One of the file descriptors that we asked for
* is no longer valid. This isn't supposed to
* happen; however, we try to handle it by testing
* each bit individually and eliminating the bad
* ones.
*/
for (fd=0; fd < nfds; fd++) {
if (FD_ISSET(fd, &fdmask)) {
do {
ready = fdmask;
timeo.tv_sec = 0;
timeo.tv_usec = 0;
k = select(nfds, &ready,
(struct fd_set *)0,
(struct fd_set *)0, &timeo);
if (k < 0 && errno == EBADF) {
fdmap[fd] = (UWIN)0;
FD_CLR(fd, &fdmask);
}
} while (n < 0 && errno == EINTR);
}
}
}
} while (n < 0 && errno == EINTR);
for (fd=0; n > 0 && fd < nfds; fd++) {
if (FD_ISSET(fd, &ready)) {
n--;
uwin = fdmap[fd];
while ((k = getmesg(fd, uwin)) > 0) {
uwin->uwi_ipclen = 0; /* for next time */
if (uwin->uwi_ipcbuf.uwip_cmd == UWC_OPTION) {
uwop = &uwin->uwi_ipcbuf.uwip_option;
uwov = &uwop->uwop_val;
optnum = ntohs(uwop->uwop_opt);
optcmd = ntohs(uwop->uwop_cmd);
if (optcmd == UWOC_SET)
uw_ntoh(uwin->uwi_type, optnum,
(char *)uwov);
if (optcmd == UWOC_SET) switch(optnum) {
case UWOP_VIS:
uwin->uwi_vis = !!uwov->uwov_6bit;
break;
case UWOP_TYPE:
if (uwov->uwov_6bit<UW_NWTYPES)
uwin->uwi_type=uwov->uwov_6bit;
break;
case UWOP_POS:
uwin->uwi_pos.uwp_v = uwov->uwov_point.v;
uwin->uwi_pos.uwp_h = uwov->uwov_point.h;
break;
case UWOP_TITLE:
(void)strncpy(uwin->uwi_title,
uwov->uwov_string,
sizeof uwin->uwi_title);
break;
case UWOP_WSIZE:
uwin->uwi_wsize.uwp_v = uwov->uwov_point.v;
uwin->uwi_wsize.uwp_h = uwov->uwov_point.h;
break;
}
if (optnum == UWOP_TYPE &&
optcmd == UWOC_SET &&
uwov->uwov_6bit < UW_NWTYPES)
uwin->uwi_type=uwov->uwov_6bit;
userfn = uwin->uwi_options[optnum].uwi_optfn;
if (userfn != (uwfnptr_t)0)
(*userfn)(uwin, optnum,
optcmd, uwov);
}
}
if (k < 0)
(void)uw_detach(uwin); /* I/O error or EOF */
}
}
(void)sigsetmask(oldmask);
/*
* Finally, if "oldsigio" is not SIG_DFL, call it.
*/
if (oldsigio != SIG_DFL)
(*oldsigio)(sig, code, scp);
}
static
getmesg(fd, uwin)
register int fd;
register UWIN uwin;
{
register int len;
register char *cp;
/*
* Read some more bytes from control socket "fd" into the input
* buffer. Return 1 if the message is now complete, -1 if an
* EOF was reached, or 0 otherwise. Before returning 1, the byte
* order of the common parameters (command, length) is changed
* from network to host order.
*/
cp = (char *)&uwin->uwi_ipcbuf + uwin->uwi_ipclen;
if (uwin->uwi_ipclen < sizeof(uwin->uwi_ipcbuf.uwip_len)) {
len = read(fd, cp, sizeof uwin->uwi_ipcbuf.uwip_len - uwin->uwi_ipclen);
if (len == 0 || (len < 0 && errno != EWOULDBLOCK))
return(-1);
if (len < 0)
return(0);
if ((uwin->uwi_ipclen +=len) < sizeof uwin->uwi_ipcbuf.uwip_len)
return(0);
uwin->uwi_ipcbuf.uwip_len = ntohs(uwin->uwi_ipcbuf.uwip_len);
if (uwin->uwi_ipcbuf.uwip_len==sizeof uwin->uwi_ipcbuf.uwip_len)
return(1);
cp += len;
}
if (uwin->uwi_ipcbuf.uwip_len > sizeof(struct uwipc))
uwin->uwi_ipcbuf.uwip_len = sizeof(struct uwipc);
len = read(fd, cp, uwin->uwi_ipcbuf.uwip_len - uwin->uwi_ipclen);
if (len == 0 || (len < 0 && errno != EWOULDBLOCK))
return(-1);
if ((uwin->uwi_ipclen += len) == uwin->uwi_ipcbuf.uwip_len) {
uwin->uwi_ipcbuf.uwip_cmd = ntohs(uwin->uwi_ipcbuf.uwip_cmd);
return(1);
} else
return(0);
}